/*
 * file options.c
 *
 * Hth's TCP Hijacker
 *
 * Hth networks
 * Copyright 2009
 * htt://www.unix-junkies.org
 * mail me at : hth at unix-junkies dot org
 *
 *
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the University of California, Berkeley nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include "options.h"
#include "flowinsert.h"
#include "common.h"


static void set_default_opt(void);


flowinsertOpt o;


void usage() {
    printf("F L O W I N S E R T  -TCP/IP Hijacking tool-\n");
    printf("  %s:%s (%s)\n", PROG_NAME, PROG_VERSION, PROG_URL);
    printf("Usage : %s [options] <injection parameters>\n", PROG_NAME);
    printf("injection parameters :\n");
    printf("  -S, --server-addr <ip addr>       Server's IP address  [REQUIRED]\n");
    printf("  -P, --server-port <port no>       Server's port        [REQUIRED]\n");
    printf("  -C, --client-addr <ip addr>       Client's IP address  [REQUIRED]\n");
    printf("options :\n");
    printf("  -I, --interface <iface>           Network interface to use\n");
    printf("  --send-client <filename>          Datas to send to client once connection hijacked\n");
    printf("  --send-server <filename>          Datas to send to server once connection hijacked\n");
    printf("\n");
}

int parse_args(int argc, char **argv) {
    int opt, index;
    long tmp;
    struct option longopt[] = {
        /* --- Long format only options --- */
        { "send-client",  no_argument,       NULL, '0' },
        { "send-server",  no_argument,       NULL, '0' },
        /* --- Both long and short format options --- */
        /* -- Arguments options -- */
        { "server-addr", required_argument,  NULL, 'S' },
        { "server-port", required_argument,  NULL, 'P' },
        { "client-addr", required_argument,  NULL, 'C' },
        { "interface",   required_argument,  NULL, 'I' },
        /* -- No argument options -- */
        { "version",     no_argument,        NULL, 'V' },
        { "help",        no_argument,        NULL, 'h' },
        { 0, 0, 0, 0 }
    };

    if (argc < 7)
        return 1;

    /* --- Set options to their default values --- */
    set_default_opt();
    /* --- *********************************** --- */
    /* --- Command line parsing loop --- */
    while ((opt = getopt_long(argc, argv, "0S:P:C:I:Vh", longopt, &index)) != -1) {
        switch(opt) {
            case    '0' :
                if (strcmp(longopt[index].name, "send-client") == 0) {
                    o.fileToClient = optarg;
                    assert(o.fileToClient[0] != '\0');  /* No NULL filename please... */
                } else if ( strcmp(longopt[index].name, "send-server") == 0 ) {
                    o.fileToServer = optarg;
                    assert(o.fileToClient[0] != '\0');
                } else {
                    /* Should never be reached */
                    fatal("WTF are we doing there?!\n");
                }
                break;

            /* Server IP address */
            case    'S' :
                o.serverAddr = optarg;
                break;

            /* Server port */
            case    'P' :
                tmp = strtol(optarg, NULL, 10);
                if (errno != EINVAL && tmp>=0x0000 && tmp<0xffff)
                    o.serverPort = (uint16_t)tmp;
                else
                    fatal("Invalid port specification for option -P (%s)\n", optarg);
                break;

            /* Client IP address */
            case    'C' :
                o.clientAddr = optarg;
                break;

            /* Network interface */
            case    'I' :
                o.iface = optarg;
                break;

            /* Print out version and exit */
            case    'V' :
                printf("%s %s ( %s )\n", PROG_NAME, PROG_VERSION, PROG_URL);
                exit(EXIT_FAILURE);

            /* Help message */
            case    'h' :
            default     :
                return 2;
        }
    }

    /* mandatory parameters */
    if (!o.serverAddr || !o.clientAddr || !o.serverPort) {
        fprintf(stderr, "[!] Not all mandatory options filled!\n");
        return 3;
    }

    if (inet_aton(o.clientAddr, &(o.clientNetAddr)) == 0) {
        fatal("[!] Invalid IP address supplied : %s", o.clientAddr);
    }

    /* If we are here, then things passed well... */
    return 0;
}


/*
 * -- --- -- --- INTERNAL STUFF --- -- --- --
 */

static void set_default_opt() {
    o.serverAddr      = NULL;
    o.clientAddr      = NULL;
    o.serverPort      = 0;
    o.iface           = NULL;
    o.fileToClient    = NULL;
    o.fileToServer    = NULL;
}

